package org.example.juc;

import java.util.HashSet;
import java.util.Set;

public class ObjectClass {
    // 如果不加volatile 此代码在并发场景下会有隐患
    private static volatile ObjectClass testClass = null;

    public int i = 0;

    private static ObjectClass testClass2 = null;

    // 构造私有化
    private ObjectClass() {
        i = 1;
    }

    public static ObjectClass getInstance() {
        // 一重检测 目的是判断是否需要初始化
        // 双重判断
//        if (testClass == null) {
//            // 加锁
//            synchronized (ObjectClass.class) {
//                // 两重检测 目的是为了判断在等锁的过程中有没有被别的线程初始化
//                if (testClass == null) {
//                    // 内部分了两步在操作
//                    // 1、<init>() 构造函数初始化
//                    // 2、putStaticField 这两步没有前后依赖关系，可能会指令重排序
//                    testClass = new ObjectClass();
//                }
//            }
//        }

        // 一重检测
        if (testClass == null) {
            synchronized (ObjectClass.class) {
                // 上一个线程释放了锁，再次进入，需要二次判断，否则，会再次进行初始化
                if (testClass == null) {
                    testClass = new ObjectClass();
                }
            }
        }
        return testClass;
    }

    public static void main(String[] args) throws InterruptedException {
        Set<Object> set = new HashSet<>();
        for (int i = 0; i < 10000; i++) {
            Thread one = new Thread(() -> {
                testClass2 = ObjectClass.getInstance();
            });
            Thread two = new Thread(() -> {
                testClass2 = ObjectClass.getInstance();
            });
            one.start();
            two.start();
            one.join();
            two.join();
            set.add(testClass2);
        }
    }
}
